package com.joolun.weixin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.joolun.common.corp.TenantContext;
import com.joolun.common.exception.base.BaseException;
import com.joolun.common.utils.DateUtils;
import com.joolun.common.utils.StringUtils;
import com.joolun.common.utils.uuid.IdUtils;
import com.joolun.system.domain.EduScheduling;
import com.joolun.system.domain.EduSchedulingClass;
import com.joolun.system.domain.ScrmCustomerAcquisition;
import com.joolun.system.domain.SysCorpConfig;
import com.joolun.system.mapper.EduSchedulingClassMapper;
import com.joolun.system.mapper.EduSchedulingMapper;
import com.joolun.system.service.IEduSchedulingService;
import com.joolun.system.service.IScrmChannelStatisticsDetailsService;
import com.joolun.system.service.impl.SysCorpConfigServiceImpl;
import com.joolun.weixin.config.WxCpConfiguration;
import com.joolun.weixin.mapper.ScrmCustomerAcquisitionMapper;
import com.joolun.weixin.service.IEduSchedulingClassService;
import com.joolun.weixin.utils.LocalDateTimeUtils;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.impl.WxCpExternalContactServiceImpl;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.external.WxCpContactWayInfo;
import me.chanjar.weixin.cp.bean.external.WxCpContactWayResult;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalUserBehaviorStatistic;
import me.chanjar.weixin.cp.bean.external.acquisition.WxCpCustomerAcquisitionInfo;
import me.chanjar.weixin.cp.bean.external.acquisition.WxCpCustomerAcquisitionRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 排期班级派量Service业务层处理
 * 
 * @author joolun
 * @date 2025-03-05
 */
@Service
@Slf4j
public class EduSchedulingClassServiceImpl extends  ServiceImpl<EduSchedulingClassMapper, EduSchedulingClass> implements IEduSchedulingClassService
{
    @Autowired
    private EduSchedulingClassMapper eduSchedulingClassMapper;

    @Autowired
    private EduSchedulingMapper eduSchedulingMapper;

    @Autowired
    private ScrmCustomerAcquisitionMapper scrmCustomerAcquisitionMapper;

    @Autowired
    private IScrmChannelStatisticsDetailsService scrmChannelStatisticsDetailsService;

    @Autowired
    private SysCorpConfigServiceImpl sysCorpConfigService;

    @Autowired
    private IEduSchedulingService iEduSchedulingService;
    /**
     * 查询排期班级派量
     * 
     * @param classId 排期班级派量主键
     * @return 排期班级派量
     */
    @Override
    public EduSchedulingClass selectEduSchedulingClassByClassId(Long classId)
    {
        return eduSchedulingClassMapper.selectEduSchedulingClassByClassId(classId);
    }

    /**
     * 查询排期班级派量列表
     * 
     * @param eduSchedulingClass 排期班级派量
     * @return 排期班级派量
     */
    @Override
    public List<EduSchedulingClass> selectEduSchedulingClassList(EduSchedulingClass eduSchedulingClass)
    {
        // 添加主体id
        eduSchedulingClass.setCorpId(TenantContext.getTenantId());
        return eduSchedulingClassMapper.selectEduSchedulingClassList(eduSchedulingClass);
    }

    /**
     * 新增排期班级派量
     * 
     * @param eduSchedulingClass 排期班级派量
     * @return 结果
     */
    @Override
    public int insertEduSchedulingClass(EduSchedulingClass eduSchedulingClass) {
        eduSchedulingClass.setCreateTime(DateUtils.getNowDate());

        // 获取主体配置
        SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(TenantContext.getTenantId());
        // 调用微信配置客户联系「联系我」方式
        WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getWxCpService(sysCorpConfig));
        WxCpContactWayInfo wxCpContactWayInfo = new WxCpContactWayInfo();
        WxCpContactWayInfo.ContactWay contactWay = new WxCpContactWayInfo.ContactWay();
        contactWay.setType(WxCpContactWayInfo.TYPE.SINGLE);
        contactWay.setScene(WxCpContactWayInfo.SCENE.QRCODE);
        contactWay.setUsers(Lists.newArrayList(eduSchedulingClass.getWecomId()));
        // 添加自定义state
        String state = IdUtils.get16UUID();
        System.out.println("创建排期班级时的state：---------------------- " + state);
        contactWay.setState(state);
        contactWay.setRemark(eduSchedulingClass.getRemark());
        wxCpContactWayInfo.setContactWay(contactWay);

        WxCpContactWayResult wxCpContactWayResult;
        try {
            wxCpContactWayResult =  externalContactService.addContactWay(wxCpContactWayInfo);
            log.info("---------------------------配置客户联系我返回结果：" + wxCpContactWayResult);
        } catch (WxErrorException e) {
            log.error("----新增班级排期，配置客户联系我异常：{}",e.getMessage());
            throw BaseException.buildBaseException(e.getError(), "配置客户联系我异常");
        }
        // 更新二维码
        eduSchedulingClass.setQrCode(wxCpContactWayResult.getQrCode());

        eduSchedulingClass.setConfigId(wxCpContactWayResult.getConfigId());
        eduSchedulingClass.setState(state);
        eduSchedulingClass.setDelFriendNum(0);
        eduSchedulingClass.setFriendNum(0);
        eduSchedulingClass.setScanNoFriend(0);
        // 添加主体id
        eduSchedulingClass.setCorpId(TenantContext.getTenantId());

        // 判断当前班级排期是否存在4，5流程，有则更新获客链接的活码企业信息
        Long schedulingId = eduSchedulingClass.getSchedulingId();
        EduScheduling eduScheduling = eduSchedulingMapper.selectOne(Wrappers.lambdaQuery(EduScheduling.class).eq(EduScheduling::getSchedulingId,schedulingId));
        // 添加班级后同步刷新获客链接码
        this.updateCustomerAcquisitionLink(eduScheduling,eduSchedulingClass.getWecomId(),"","add");

        return eduSchedulingClassMapper.insertEduSchedulingClass(eduSchedulingClass);
    }

    /**
     * 修改排期班级派量
     * 
     * @param eduSchedulingClass 排期班级派量
     * @return 结果
     */
    @Override
    public int updateEduSchedulingClass(EduSchedulingClass eduSchedulingClass) {
        eduSchedulingClass.setUpdateTime(DateUtils.getNowDate());

        EduSchedulingClass schedulingClassUpdate = eduSchedulingClassMapper.selectById(eduSchedulingClass.getClassId());
        String oldWecomId = schedulingClassUpdate.getWecomId();

        // 关联企业微信修改
        if(!eduSchedulingClass.getWecomId().equals(oldWecomId)){
            // 获取主体配置
            SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(TenantContext.getTenantId());
            String configId = schedulingClassUpdate.getConfigId();
            //TODO： 调用企微更新企业已配置的「联系我」方式
            WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getWxCpService(sysCorpConfig));
            WxCpContactWayInfo wxCpContactWayInfo = new WxCpContactWayInfo();
            WxCpContactWayInfo.ContactWay contactWay = new WxCpContactWayInfo.ContactWay();
            contactWay.setConfigId(configId);
            contactWay.setUsers(Lists.newArrayList(eduSchedulingClass.getWecomId()));
            wxCpContactWayInfo.setContactWay(contactWay);

            WxCpBaseResp wxCpBaseResp;
            try {
                wxCpBaseResp =  externalContactService.updateContactWay(wxCpContactWayInfo);

            } catch (WxErrorException e) {
                log.error("----修改企业已配置的「联系我」方式异常：{}",e.getMessage());
                throw BaseException.buildBaseException(e.getError(), "修改配置企业已配置的「联系我」方式异常");
            }

            // TODO:查看修改的排期的投放计划是否又4，5方式，有则更新获客链接。把修改前的userId微信换成新的
            Long schedulingId = eduSchedulingClass.getSchedulingId();
            EduScheduling eduScheduling = eduSchedulingMapper.selectOne(Wrappers.lambdaQuery(EduScheduling.class).eq(EduScheduling::getSchedulingId,schedulingId));
            this.updateCustomerAcquisitionLink(eduScheduling,eduSchedulingClass.getWecomId(),oldWecomId,"update");
        }


        return eduSchedulingClassMapper.updateEduSchedulingClass(eduSchedulingClass);
    }


    /**
     * 修改获客链接
     * @param eduScheduling
     * @param newUserIds
     */
    private void  updateCustomerAcquisitionLink(EduScheduling eduScheduling,String newUserIds,String oldUserIds,String type){
        // 排期的课程ID
        Long courseId = eduScheduling.getCourseId();
        // 修改获客链接码的人数
        ScrmCustomerAcquisition scrmCustomerAcquisition = scrmCustomerAcquisitionMapper.selectOne(Wrappers.lambdaQuery(ScrmCustomerAcquisition.class).eq(ScrmCustomerAcquisition::getCourseId,courseId));
        if(scrmCustomerAcquisition !=null && StringUtils.isNotEmpty(scrmCustomerAcquisition.getConfigId())){
            // 当前获客链接如果没有排期，则设置排期id
            if(scrmCustomerAcquisition.getSchedulingId() == null && scrmCustomerAcquisition.getSchedulingId() == ""){
                scrmCustomerAcquisition.setSchedulingId(eduScheduling.getSchedulingId().toString());
            }else {
                // 如果两次排期不一致，则进入验证
                if(!eduScheduling.getSchedulingId().toString().equals(scrmCustomerAcquisition.getSchedulingId())){
                    // 验证两个排期时间优先级，取排期开始时间靠后的排期
                    List<EduScheduling> eduSchedulingList = iEduSchedulingService.list(Wrappers.lambdaQuery(EduScheduling.class)
                            .in(EduScheduling::getSchedulingId,Arrays.asList(scrmCustomerAcquisition.getSchedulingId(),eduScheduling.getSchedulingId()))
                            .lt(EduScheduling::getEnrollStartTime, DateUtils.getNowDate())
                            .gt(EduScheduling::getEnrollEndTime, DateUtils.getNowDate())
                            .orderByDesc(EduScheduling::getEnrollStartTime));
                    log.info("------------------符合当前时间的课程排期:{}",eduSchedulingList.size());
                    // 取第一个排期
                    scrmCustomerAcquisition.setSchedulingId(eduSchedulingList.get(0).getSchedulingId().toString());
                }
            }
            String existUserIds = scrmCustomerAcquisition.getExtId();
            String linkId = scrmCustomerAcquisition.getConfigId();
            try {
                // 先获取已有的获客链接的人数再把新增的人加进去
                WxCpCustomerAcquisitionRequest wxCpCustomerAcquisitionRequest = new WxCpCustomerAcquisitionRequest();
                wxCpCustomerAcquisitionRequest.setLinkId(linkId);
                WxCpCustomerAcquisitionInfo.Range range  = new WxCpCustomerAcquisitionInfo.Range();
                // 添加排期班级修改获客链接
                List<String> userList = null;
                // 清理方括号
                String cleanExistUserId = existUserIds;
                if (cleanExistUserId != null && cleanExistUserId.startsWith("[") && cleanExistUserId.endsWith("]")) {
                    cleanExistUserId = cleanExistUserId.substring(1, cleanExistUserId.length() - 1);
                }
                if(type.equals("add")){
                    // 1.解析现有用户ID（处理逗号分隔和去重）
                    Set<String> uniqueUsers = new LinkedHashSet<>();
                    if (cleanExistUserId != null && !cleanExistUserId.isEmpty()) {
                        // 拆分现有用户ID并添加到集合（自动去重）
                        Arrays.stream(cleanExistUserId.split(","))
                                .map(String::trim)
                                .filter(s -> !s.isEmpty())
                                .forEach(uniqueUsers::add);

//                        String[] existIds = cleanExistUserId.split(",");
//                        uniqueUsers.addAll(Arrays.asList(existIds));
                    }
                    // 2.新的码追加到获客链接
                    uniqueUsers.add(newUserIds);
                    // 3.转换为可修改的列表（避免不可变列表问题）
                    userList = new ArrayList<>(uniqueUsers);
//                    userList = Lists.newArrayList(newUserIds,cleanExistUserId);
                    log.info("-----------添加此获客链接:{}关联的userid列表:{}",linkId,userList);
                }else if(type.equals("delete")){
                    // 将 cleanExistUserId 拆分并转为可修改的列表
                    userList = Arrays.stream(cleanExistUserId.split(","))
                            .map(String::trim)
                            .filter(id -> !id.isEmpty())
                            .collect(Collectors.toList());
                    // 将 newUserIds 拆分并转为集合（使用 Set 提高查找效率）
                    Set<String> newUserIdSet = Arrays.stream(newUserIds.split(",")).map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toSet());
                    // 安全删除匹配的元素
                    userList.removeIf(newUserIdSet::contains);
                    log.info("-----------删除此获客链接成员:{}关联的userid列表:{}",linkId, userList);
                    // 如果移除后成员列表为空，处理方式
//                    if (userList.isEmpty()) {
//                        throw new IllegalArgumentException("不能移除所有成员，获客链接必须至少有一个成员");
//                    }
                }else {
                    // TODO:替换旧码的userId为新码
                    List<String> userLists = Arrays.asList(cleanExistUserId.split(","));
                    // 检查是否包含 oldUserIds，若包含则替换为 newUserIds
                    if (userLists.contains(oldUserIds)) {
                        userList = userLists.stream()
                                .map(user -> user.equals(oldUserIds) ? newUserIds : user)
                                .collect(Collectors.toList());
                    }
                    log.info("----编辑此获客链接:{}关联的userid列表:{} 更新->{}",linkId,oldUserIds,newUserIds);
                }
                range.setUserList(userList);
                wxCpCustomerAcquisitionRequest.setRange(range);
                // 获取主体配置
                SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(TenantContext.getTenantId());
                WxCpExternalContactService wxCpExternalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getCustomerSecretWxCpService(sysCorpConfig));
                WxCpBaseResp wxCpBaseResp = wxCpExternalContactService.customerAcquisitionUpdate(wxCpCustomerAcquisitionRequest);
                // 检查返回结果
                log.info("------------修改获客链接接口返回:{}",wxCpBaseResp);
                if (wxCpBaseResp.getErrcode() != 0) {
                    log.error("更新获客链接失败: {}", wxCpBaseResp.getErrmsg());
                    throw new RuntimeException("更新获客链接失败，请联系管理员！");
                } else {
                    // 更新获客链接
                    String userExtId = String.join(",", userList);
                    scrmCustomerAcquisition.setExtId(userExtId);
                    scrmCustomerAcquisition.setUpdateTime(DateUtils.getNowDate());
                    scrmCustomerAcquisitionMapper.updateScrmCustomerAcquisition(scrmCustomerAcquisition);
                    log.info("----------更新获客链接成功");
                }
            } catch (WxErrorException e) {
                log.error("--调用企微修改获客助手接口异常：{}",e.getMessage());
                throw new RuntimeException("获客链接异常，请联系管理员！");
            }
        }
    }


    /**
     * 批量删除排期班级派量
     * 
     * @param classIds 需要删除的排期班级派量主键
     * @return 结果
     */
    @Override
    public int deleteEduSchedulingClassByClassIds(Long[] classIds)
    {
        // 因为每个班级都对应同一个排期id,所以取第一个即可
        EduSchedulingClass schedulingClassDel = eduSchedulingClassMapper.selectById(classIds[0]);
        // 获取第一个班级人员的userId
        String wecomIdStr = schedulingClassDel.getWecomId();
        // 如果有多个班级人员，则获取所有的userId
        if(classIds.length > 1){
            List<EduSchedulingClass> classList = eduSchedulingClassMapper.selectClassByIdList(classIds);
            // 提取每个对象的 WecomId，然后用逗号连接成字符串
            wecomIdStr = classList.stream()
                    .map(EduSchedulingClass::getWecomId)  // 提取 WecomId 属性
                    .collect(Collectors.joining(","));  // 用逗号连接
        }
        EduScheduling eduScheduling = eduSchedulingMapper.selectOne(Wrappers.lambdaQuery(EduScheduling.class).eq(EduScheduling::getSchedulingId,schedulingClassDel.getSchedulingId()));
        this.updateCustomerAcquisitionLink(eduScheduling,wecomIdStr,"","delete");
        return eduSchedulingClassMapper.deleteEduSchedulingClassByClassIds(classIds);
    }

    /**
     * 删除排期班级派量信息
     * 
     * @param classId 排期班级派量主键
     * @return 结果
     */
    @Override
    public int deleteEduSchedulingClassByClassId(Long classId)
    {
        return eduSchedulingClassMapper.deleteEduSchedulingClassByClassId(classId);
    }

    @Override
    public int updateFriendNum(EduSchedulingClass eduSchedulingClass){
        return eduSchedulingClassMapper.updateFriendNum(eduSchedulingClass);
    }


    /**
     * 获取有效的排期联系人的获客统计数据
     */
    @Override
    public void getUserBehaviorData(){
        // 查找课程查找排期计划里的所有符合当前时间的班级
        List<EduScheduling> eduSchedulingList = eduSchedulingMapper.selectList(Wrappers.lambdaQuery(EduScheduling.class)
                //.eq(EduScheduling::getCourseId, courseId)
                .lt(EduScheduling::getEnrollStartTime, DateUtils.getNowDate())
                .gt(EduScheduling::getEnrollEndTime, DateUtils.getNowDate())
                .orderByAsc(EduScheduling::getEnrollStartTime));
        log.info("--符合当前时间的课程排期:{}",eduSchedulingList.size());

        if(CollectionUtil.isEmpty(eduSchedulingList)){
            return;
        }
        // 排期id
        List<Long> ids = eduSchedulingList.stream().map(item->item.getSchedulingId()).collect(Collectors.toList());

        // 查询排期班级信息
        List<EduSchedulingClass> eduSchedulingClassList =  list(Wrappers.lambdaQuery(EduSchedulingClass.class)
                .in(EduSchedulingClass::getSchedulingId,ids));
        // 当天的开始时间
        Date startTime = LocalDateTimeUtils.startTimeOfDay();
        Date endTime = DateUtils.getNowDate();
        log.info("----查询企微的获客统计数据时间：{}-{}",startTime,endTime);
        // 获取主体配置
        SysCorpConfig sysCorpConfig = sysCorpConfigService.getConfig(TenantContext.getTenantId());
        if(CollectionUtil.isNotEmpty(eduSchedulingClassList)){
            eduSchedulingClassList.forEach(item ->{
                // 调用企微获取「联系客户统计」数据
                WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(WxCpConfiguration.getCustomerSecretWxCpService(sysCorpConfig));
                try {
                    String userIds[] = new String[1];
                    // 排期的企微用户
                    userIds[0] = item.getWecomId();
                    WxCpUserExternalUserBehaviorStatistic wxCpUserExternalUserBehaviorStatistic = externalContactService.getUserBehaviorStatistic(startTime,endTime, userIds  ,null);
                    List<WxCpUserExternalUserBehaviorStatistic.Behavior> behaviorList = wxCpUserExternalUserBehaviorStatistic.getBehaviorList();
                    log.info("----查询企微:{}联系客户统计返回：{}", userIds[0],JSONObject.toJSONString(behaviorList));

                    WxCpUserExternalUserBehaviorStatistic.Behavior behavior =  behaviorList.get(0);
                    // 新增客户数
                    Integer newContactCnt =  behavior.getNewContactCnt();
                    Integer chatCnt = behavior.getChatCnt();
                    Integer negativeFeedbackCnt = behavior.getNegativeFeedbackCnt();
                    Integer newApplyCnt = behavior.getNewApplyCnt();
                    // 更新班级数据
                    item.setFriendNum(item.getFriendNum() + newContactCnt);
                    item.setDelFriendNum(item.getDelFriendNum() + negativeFeedbackCnt);
                    super.saveOrUpdate(item);
                    // 更新统计数据
                    //scrmChannelStatisticsDetailsService.save();
                } catch (WxErrorException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

}
